﻿#include "GLLInc.h"
#include "GLLLevel.h"
#include "GLLMacro.h"
#include "GLLObjSpcl.h"
#include "GLLTimer.h"
#include "GLLTheSystem.h"
#include "GLLResMgr.h"
#include "GLLLevelManager.h"

#define LOCK_OBJECTS	LOCK_MUTEX(_objMutex)


namespace GLL
{

	void Level::PutToLoadQueue( ObjSrdPtr ptr)
	{
		If_Life_Is_Over_Return;
		LvlObjSrdPtr pObj = boost::dynamic_pointer_cast<LvlObj>(ptr);

		//只有刚刚创建出来的干净物体，才配Load
		if(!pObj->HasLifeStatus(LvlObj::LS_Created))
		{
			SS ss; ss << pObj->StrID() << " not just created.";
			GLL_Throw(ss);
		}

		_preThread.PutToQueue(pObj);
	}

	void Level::PutToUnloadQueue(LvlObj::ID oid)
	{
		LvlObjSrdPtr ptr = boost::dynamic_pointer_cast<LvlObj>(_DestroyObject(oid));
		//ptr->SetVisible(false);
		//交给删除队列去管理
		_unloadingThread.PutToQueue(ptr);
	}

	void Level::PushAllOjbectsToUnloadQueue()
	{
		ObjectVec objVec;
		_GetTempObjectVec(objVec);

		BOOST_FOREACH(ObjSrdPtr ptr, objVec)
		{
			if(!ptr){
				GLL_BreakPoint;
			}else{
				PutToUnloadQueue(ptr->GetID());
			}
		}
	}

	LvlObjSrdPtr Level::CreateObject( LvlObj::ID oid)
	{
		If_Life_Is_Over_Return LvlObjSrdPtr();
		switch(oid.type)
		{
		case Object::OT_Mesh:
		case Object::OT_Light:
			break;
		default:
			return LvlObjSrdPtr();
		}
		LvlObjSrdPtr srdPtr = boost::dynamic_pointer_cast<LvlObj>(_CreateObject(oid));
		srdPtr->SetLifeStatus(LvlObj::LS_Created);
		return srdPtr;
	}

	void Level::Init()
	{
		//创建物品线程 启动
		Index idx = AddLoadingThread();
		LevelThreadLoad* pTL = GetLoadingThread(idx);
		pTL->Start();
		//删除物品线程 启动
		_unloadingThread.Start();

		OnInit_spec();
		theGame()->_resMgr->LoadLevelRes_spec(*this);
	}

	String Level_MakeStrID(Level::ID id)
	{
		StringStream strm;
		strm << "LVL." << id;
		String ret(strm.str());
		return ret;
	}

	Level::Level(LevelManager* p, ID id) 
		: _Mgr(p), 
		_id(id), 
		_strID(Level_MakeStrID(id)),
		_unloadingThread(this), //OK. warning C4355
		_preThread(this),
		_postThread(this),
		_ploadThread(this)
	{
		_lifeIsOver = false;
		_event = 0;
	}

	void Level::Final()
	{
		_lifeIsOver = true;

		//清理顺序很重要:
		//未加载的 直接清理
		_preThread.ClearList();

		//正在加载的 等待完成
		uint threadNum = GetLoadingThreadNum();
		for(Index i = 0; i < threadNum; i++)
		{
			LevelThreadLoad* pTL = GetLoadingThread(i);
			pTL->WaitingFinished();
			//删除
			DeleteLoadingThread(pTL);
		}

		//后期处理，放弃
		_ploadThread.ClearList();

		//已经加载的 放入卸载队列
		PushAllOjbectsToUnloadQueue();

		//正在卸载的 等待完成
		_unloadingThread.WaitingFinished();

		//正在后期处理的 等待完成
		_postThread.WaitingFinished();

		//特别需求
		OnFinal_spec();

		//资源清理
		theGame()->_resMgr->UnloadLevelRes_spec(*this);
	}

	Index Level::AddLoadingThread()
	{
		If_Life_Is_Over_Return nullindex;

		LevelThreadLoad* pTL = GLL_NEW LevelThreadLoad(this);
		_loadingThreads.push_back(pTL);
		return GetLoadingThreadNum() - 1;
	}

	void Level::RemoveFirstLoadingThread()
	{
		LoadingThreadVec::iterator iter = _loadingThreads.begin();
		if(iter != _loadingThreads.end())
		{
			LevelThreadLoad* pTL = *iter;
			GLL_DEL(pTL);
			_loadingThreads.erase(iter);
		}
	}

	uint Level::GetLoadingThreadNum()
	{
		return _loadingThreads.size();		
	}

	LevelThreadLoad* Level::GetLoadingThread( Index id )
	{
		uint num = GetLoadingThreadNum();
		if(id < 0 || id >= num) return 0;
		return _loadingThreads[id];
	}

	//线程分配策略：均匀分配
	LevelThreadLoad* Level::GetLoadingThread()
	{
		static Index thisTurn = 0;
		uint num = GetLoadingThreadNum();
		bool condition = true;
		while(condition)
		{
			if(thisTurn >= num) thisTurn = 0;
			LevelThreadLoad* pTL = GetLoadingThread(thisTurn);
			thisTurn++;

			if(!pTL) continue;
			if(pTL->_Stop) continue;
			if(pTL->_threadFinished) continue;

			return pTL;
		}

		return 0;
	}

	void Level::DeleteLoadingThread(LevelThreadLoad* p)
	{
		LoadingThreadVec::iterator iter = _loadingThreads.begin();
		LoadingThreadVec::iterator end = _loadingThreads.end();

		for(; iter != end; ++iter)
		{
			LevelThreadLoad* pTL = *iter;
			if(pTL == p){
				GLL_DEL(p);
				_loadingThreads.erase(iter);
				break;
			}
		}
	}

	void Level::SetEventCallback( LevelEvent* e )
	{
		_event = e;
	}

	void Level::Update(TimeMS ms)
	{
		If_Life_Is_Over_Return;
		if( _unloadingThread._1Thread)
		{
			_unloadingThread.DoOnce();
		}

		if( _preThread._1Thread)
		{
			_preThread.DoOnce();
		}

		if( _ploadThread._1Thread)
		{
			_ploadThread.DoOnce();
		}

		if( _postThread._1Thread)
		{
			_postThread.DoOnce();
		}

		BOOST_FOREACH(LevelThreadLoad* pTL, _loadingThreads)
		{
			if( pTL->_1Thread) pTL->DoOnce();
		}
		Update_AllObjects(ms);
	}

	void Level::AddCamera( CamSrdPtr ptr)
	{
		ptr->_Add2Level(this);
	}

	void Level::RemoveCamera(CamSrdPtr ptr)
	{
		ptr->_RemoveFromLevel(this);
	}


};//GLL


namespace boost
{
	void checked_delete(GLL::Level* x)
	{
		if(!x) return;
		assert(x->_Mgr);
		x->_Mgr->_delete_Level(x);
	}
}
